package com.neusoft.elmboot.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.neusoft.elmboot.exception.exceptions.BaseException;
import com.neusoft.elmboot.exception.exceptions.ErrorStateException;
import com.neusoft.elmboot.exception.exceptions.IllegalAmountException;
import com.neusoft.elmboot.mapper.WalletMapper;
import com.neusoft.elmboot.po.User;
import com.neusoft.elmboot.po.dto.WalletInfoDTO;
import com.neusoft.elmboot.po.vo.WalletTransactionVO;
import com.neusoft.elmboot.po.wallet.VirtualWallet;
import com.neusoft.elmboot.po.wallet.WalletTransaction;
import com.neusoft.elmboot.po.wallet.WalletRule;
import com.neusoft.elmboot.service.UserService;
import com.neusoft.elmboot.service.WalletService;
import com.neusoft.elmboot.service.WalletRuleService;
import com.neusoft.elmboot.util.WalletUtils;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.security.crypto.bcrypt.BCrypt;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.List;

@Service
@Transactional(rollbackFor = Exception.class)
@Slf4j
public class WalletServiceImpl extends ServiceImpl<WalletMapper, VirtualWallet> implements WalletService {
    @Resource
    private WalletMapper walletMapper;

    @Resource
    private BCryptPasswordEncoder encoder;

    @Resource
    private WalletRuleService walletRuleService;

    @Resource
    private UserService userService;

    /**
     * 根据用户等级计算默认透支额度
     */
    private BigDecimal getOverdraftLimitByUserLevel(String walletId) {
        try {
            User user = userService.getUserInfoById(walletId);
            int level = (user != null && user.getLevel() != null) ? user.getLevel() : 1;
            switch (level) {
                case 1:
                    return BigDecimal.valueOf(500);
                case 2:
                    return BigDecimal.valueOf(1000);
                case 3:
                    return BigDecimal.valueOf(2000);
                case 4:
                    return BigDecimal.valueOf(3000);
                default:
                    return BigDecimal.valueOf(5000);
            }
        } catch (Exception e) {
            // 出现异常时使用保守默认值
            return BigDecimal.valueOf(500);
        }
    }

    private void checkWallet(VirtualWallet wallet) throws BaseException {
        if (wallet == null) {
            throw new ErrorStateException("用户不存在");
        }
    }

    @Override
    public Integer init(String walletId, String payPwd) throws BaseException {
        if (walletId == null || payPwd == null){
            throw new ErrorStateException("用户或密码为空");
        } else if (walletMapper.selectById(walletId) != null) {
            throw new ErrorStateException("用户已存在");
        } else {
            payPwd = encoder.encode(payPwd);
            VirtualWallet wallet = new VirtualWallet(walletId, payPwd);
            return walletMapper.insert(wallet);
        }
    }

    @Override
    public void setVIP(List<String> walletIdList) throws BaseException {
        if (walletIdList.isEmpty()) {
            throw new ErrorStateException("用户不能为空");
        } else {
            walletMapper.setVIP(walletIdList);
            // 设置VIP后，自动为每个用户根据等级设置默认透支额度
            for (String walletId : walletIdList) {
                VirtualWallet wallet = walletMapper.selectById(walletId);
                if (wallet != null && (wallet.getOverdraftAmount() == null ||
                    wallet.getOverdraftAmount().compareTo(BigDecimal.ZERO) == 0)) {
                    BigDecimal defaultOverdraftAmount = getOverdraftLimitByUserLevel(walletId);
                    walletMapper.setOverdraftAmount(walletId, defaultOverdraftAmount);
                    log.info("为VIP用户根据等级设置默认透支额度: walletId={}, amount={}", walletId, defaultOverdraftAmount);
                }
            }
        }
    }

    @Override
    public void setOverdraftAmount(String walletId, BigDecimal amount) throws BaseException{
        VirtualWallet wallet = walletMapper.selectById(walletId);
        if (wallet == null) {
            throw new ErrorStateException("用户为空");
        }
        WalletRule rule = walletRuleService.getRechargeRule();
        BigDecimal minAmount = rule.getMinOverdraftAmount();
        BigDecimal maxAmount = rule.getMaxOverdraftAmount();
        if (amount.compareTo(minAmount) < 0 || amount.compareTo(maxAmount) > 0) {
            throw new IllegalAmountException("金额异常");
        } else {
            if (!wallet.getIsVIP()) {
                throw new ErrorStateException("非VIP不能透支");
            } else {
                walletMapper.setOverdraftAmount(walletId, amount);
            }
        }
    }

    @Override
    public VirtualWallet getInfo(String walletId) throws BaseException {
        // 使用显式SQL查询，确保获取最新数据
        VirtualWallet wallet = walletMapper.getWalletById(walletId);
        checkWallet(wallet);
        wallet.hidePwd();
        return wallet;
    }

    @Override
    public WalletInfoDTO getWalletInfo(String walletId) throws BaseException {
        // 使用显式SQL查询，确保获取最新数据
        VirtualWallet wallet = walletMapper.getWalletById(walletId);
        checkWallet(wallet);

        // 转换为DTO，确保金额格式正确
        WalletInfoDTO dto = new WalletInfoDTO();
        dto.setWalletId(wallet.getId());

        // 将BigDecimal转换为字符串，保留两位小数
        BigDecimal balance = wallet.getBalance() != null ? wallet.getBalance() : BigDecimal.ZERO;
        BigDecimal frozen = wallet.getFrozenAmount() != null ? wallet.getFrozenAmount() : BigDecimal.ZERO;
        // 可用余额使用钱包的可支配金额（包含透支额度）
        BigDecimal available = wallet.getAvailableBalance();

        dto.setBalance(balance.setScale(2, RoundingMode.HALF_UP).toString());
        dto.setFrozenAmount(frozen.setScale(2, RoundingMode.HALF_UP).toString());
        dto.setAvailableBalance(available.setScale(2, RoundingMode.HALF_UP).toString());

        dto.setIsVIP(wallet.getIsVIP() != null ? wallet.getIsVIP() : false);
        dto.setIsAllowedOverdraft(wallet.getIsAllowedOverdraft() != null ? wallet.getIsAllowedOverdraft() : false);

        if (wallet.getOverdraftAmount() != null) {
            dto.setOverdraftAmount(wallet.getOverdraftAmount().setScale(2, RoundingMode.HALF_UP).toString());
        } else {
            dto.setOverdraftAmount("0.00");
        }

        if (wallet.getCurrentOverdraftAmount() != null) {
            dto.setCurrentOverdraftAmount(wallet.getCurrentOverdraftAmount().setScale(2, RoundingMode.HALF_UP).toString());
        } else {
            dto.setCurrentOverdraftAmount("0.00");
        }

        // 生成最晚还款日期：如果存在透支，则给出一个参考日期（例如30天后）
        if (wallet.getCurrentOverdraftAmount() != null &&
            wallet.getCurrentOverdraftAmount().compareTo(BigDecimal.ZERO) > 0) {
            LocalDate deadline = LocalDate.now().plusDays(30);
            DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
            dto.setRepayDeadline(deadline.format(formatter));
        } else {
            dto.setRepayDeadline(null);
        }

        return dto;
    }

    @Override
    public List<WalletTransactionVO> getTransInfo(String walletId, Integer index) throws Exception {
        if (walletMapper.selectById(walletId) == null) {
            throw new ErrorStateException("用户不存在");
        } else {
            if (index.equals(WalletUtils.incomeIndex)) {
                return walletMapper.getIncomeTrans(walletId);
            } else if (index.equals(WalletUtils.outcomeIndex)) {
                return walletMapper.getOutcomeTrans(walletId);
            } else {
                return walletMapper.getTransByWalletId(walletId);
            }
        }
    }

    @Override
    public void recharge(String walletId, BigDecimal amount) throws BaseException {
        VirtualWallet wallet = walletMapper.selectById(walletId);
        if (wallet == null) {
            // 如果钱包不存在，自动创建钱包（使用默认支付密码）
            log.warn("钱包不存在，自动创建钱包: {}", walletId);
            try {
                init(walletId, "123456"); // 使用默认支付密码
                wallet = walletMapper.selectById(walletId);
                if (wallet == null) {
                    throw new ErrorStateException("钱包创建失败，请稍后重试");
                }
            } catch (Exception e) {
                log.error("自动创建钱包失败: {}", e.getMessage());
                throw new ErrorStateException("钱包创建失败，请稍后重试");
            }
        }
        
        if (amount == null || amount.compareTo(BigDecimal.ZERO) <= 0) {
            throw new IllegalAmountException("充值金额必须大于0");
        }
        
        // 检查VIP用户是否需要先还款
        if (wallet.getIsVIP() != null && wallet.getIsVIP() && 
            wallet.getIsAllowedOverdraft() != null && !wallet.getIsAllowedOverdraft() &&
            wallet.getCurrentOverdraftAmount() != null && wallet.getCurrentOverdraftAmount().compareTo(BigDecimal.ZERO) > 0) {
            throw new ErrorStateException("请先还款");
        }
        
        // 计算赠送金额
        BigDecimal originalAmount = amount;
        WalletRule rule = walletRuleService.getRechargeRule();
        if (rule != null) {
            BigDecimal rechargeLevel = rule.getRechargeLevel();
            BigDecimal rechargeGift = rule.getRechargeGift();
            if (rechargeLevel != null && rechargeGift != null && rechargeLevel.compareTo(BigDecimal.ZERO) > 0) {
                BigDecimal levels = amount.divide(rechargeLevel, RoundingMode.FLOOR);
                BigDecimal extra = levels.multiply(rechargeGift);
                amount = amount.add(extra);
                log.info("充值计算: 原始金额={}, 充值等级={}, 赠送={}, 最终金额={}", 
                    originalAmount, rechargeLevel, extra, amount);
            }
        }
        
        // 创建交易记录
        WalletTransaction transaction = new WalletTransaction(walletId, walletId, originalAmount);
        transaction.unfreeze();
        
        // 执行充值
        walletMapper.recharge(walletId, amount);
        walletMapper.addTrans(transaction);
        
        log.info("充值成功: walletId={}, 原始金额={}, 实际到账={}", walletId, originalAmount, amount);
    }

    @Override
    public void repay(String walletId, BigDecimal amount) throws BaseException {
        VirtualWallet wallet = walletMapper.selectById(walletId);
        if (wallet == null) {
            throw new ErrorStateException("用户不存在");
        } else {
            wallet.repay(amount);
            walletMapper.updateById(wallet);
        }
    }

    @Override
    public void borrow(String walletId, BigDecimal amount) throws BaseException {
        VirtualWallet wallet = walletMapper.selectById(walletId);
        if (wallet == null) {
            throw new ErrorStateException("用户不存在");
        }
        
        if (amount == null || amount.compareTo(BigDecimal.ZERO) <= 0) {
            throw new IllegalAmountException("借贷金额必须大于0");
        }
        
        // 获取透支规则，检查借贷金额是否在允许范围内
        WalletRule rule = walletRuleService.getRechargeRule();
        BigDecimal minAmount = rule.getMinOverdraftAmount();
        BigDecimal maxAmount = rule.getMaxOverdraftAmount();
        
        if (minAmount != null && amount.compareTo(minAmount) < 0) {
            throw new IllegalAmountException("借贷金额不能少于" + minAmount + "元");
        }
        
        // 检查钱包的透支额度，如果为0或null，根据用户等级设置默认额度
        BigDecimal walletOverdraftAmount = wallet.getOverdraftAmount();
        if (walletOverdraftAmount == null || walletOverdraftAmount.compareTo(BigDecimal.ZERO) == 0) {
            BigDecimal levelLimit = getOverdraftLimitByUserLevel(walletId);
            // 如果规则中配置了最大透支额度，则取等级额度和规则额度的较小值
            if (maxAmount != null && maxAmount.compareTo(BigDecimal.ZERO) > 0
                && levelLimit.compareTo(maxAmount) > 0) {
                levelLimit = maxAmount;
            }
            wallet.setOverdraftAmount(levelLimit);
            wallet.openOverdraft(); // 允许透支
            log.info("为钱包根据用户等级设置默认透支额度: walletId={}, amount={}", walletId, levelLimit);
        }
        
        if (maxAmount != null) {
            // 检查借贷后总透支金额是否超过最大透支额度
            BigDecimal currentOverdraft = wallet.getCurrentOverdraftAmount() != null ?
                wallet.getCurrentOverdraftAmount() : BigDecimal.ZERO;
            BigDecimal newOverdraft = currentOverdraft.add(amount);
            if (newOverdraft.compareTo(maxAmount) > 0) {
                throw new IllegalAmountException("借贷金额超过最大透支额度" + maxAmount + "元");
            }
        }
        
        // 执行借贷
        wallet.borrow(amount);
        walletMapper.updateById(wallet);
        
        // 创建交易记录
        WalletTransaction transaction = new WalletTransaction(walletId, walletId, amount);
        transaction.unfreeze();
        walletMapper.addTrans(transaction);
        
        log.info("借贷成功: walletId={}, 借贷金额={}, 当前透支={}", 
            walletId, amount, wallet.getCurrentOverdraftAmount());
    }

    @Override
    public BigDecimal withdraw(String walletId, String payPwd, BigDecimal amount) throws BaseException {
        VirtualWallet wallet = walletMapper.selectById(walletId);
        checkWallet(wallet);
        if (amount.compareTo(BigDecimal.ZERO) < 0) {
            throw new IllegalAmountException("提现金额异常");
        } else {
            WalletTransaction transaction = new WalletTransaction(walletId, walletId, amount);
            transaction.unfreeze();
            String encodedPwd = wallet.getPayPwd();
            BigDecimal balance = wallet.getBalance();
            if (amount.compareTo(balance) > 0) {
                throw new IllegalAmountException("余额不足，无法提现");
            } else if (wallet.getCurrentOverdraftAmount().compareTo(BigDecimal.ZERO) > 0) {
                throw new ErrorStateException("请先还款");
            } else if (!BCrypt.checkpw(payPwd, encodedPwd)){
                throw new ErrorStateException("密码错误");
            } else {
                balance = balance.subtract(amount);
                walletMapper.withdraw(walletId, balance);
                walletMapper.addTrans(transaction);
                // 从规则配置获取提现规则
                WalletRule rule = walletRuleService.getWithdrawRule();
                BigDecimal withdrawRate = rule.getWithdrawRate();
                if (withdrawRate == null) {
                    withdrawRate = BigDecimal.valueOf(0.9); // 默认90%
                }
                return balance.multiply(withdrawRate);
            }
        }
    }

    @Override
    public String pay(String fromWalletId, String toWalletId, String payPwd, BigDecimal amount) throws BaseException {
        // 只检查用户钱包
        VirtualWallet fromWallet = walletMapper.selectById(fromWalletId);
        if (fromWallet == null){
            throw new ErrorStateException("用户钱包不存在");
        }
        
        if (amount.compareTo(BigDecimal.ZERO) < 0) {
            throw new IllegalAmountException("交易金额异常");
        }
        
        String encodedPwd = fromWallet.getPayPwd();
        
        // 检查支付密码
        if (!BCrypt.checkpw(payPwd, encodedPwd)){
            throw new ErrorStateException("密码错误");
        }
        
        // 只扣减用户钱包余额，不处理商家钱包
        fromWallet.debit(amount);
        walletMapper.updateById(fromWallet);
        
        // 创建交易记录（可选，用于记录）
        WalletTransaction transaction = new WalletTransaction(fromWalletId, toWalletId, amount);
        walletMapper.addTrans(transaction);
        
        return transaction.getTransId();
    }

    @Override
    public void confirm(String transId) throws BaseException{
        WalletTransaction transaction = walletMapper.getTrans(transId);
        if (transaction == null) {
            throw new ErrorStateException("订单不存在");
        } else {
            if (!transaction.getIsValid()) {
                throw new ErrorStateException("订单失效");
            } else {
                VirtualWallet toWallet = walletMapper.selectById(transaction.getToWalletId());
                toWallet.unfreeze(transaction.getAmount());
                toWallet.credit(transaction.getAmount());
                transaction.unfreeze();
                walletMapper.updateById(toWallet);
                walletMapper.updateTransState(transId,false, null);
            }
        }
    }


//    @Scheduled(cron = "0/10 * * * * ?")
    @Scheduled(cron = "0 0 4 * * ?")
    public void cleanFrozenTrans() throws BaseException{
        List<String> frozenTransList = walletMapper.getFrozenTransId();

        for (String transId : frozenTransList) {
            confirm(transId);
            log.info(transId);
        }
    }


//    @Scheduled(cron = "0/10 * * * * ?")
    @Scheduled(cron = "0 0 4 * * ?")
    public void updateRepayAmount() throws BaseException{
        List<String> overdraftIdList = walletMapper.getOverdraftId();
        for (String id : overdraftIdList) {
            VirtualWallet wallet = walletMapper.selectById(id);
            checkWallet(wallet);
            if (!wallet.getIsVIP()) {
                throw new ErrorStateException("用户VIP状态异常");
            } else {
                BigDecimal cur = wallet.getCurrentOverdraftAmount();
                // 从规则配置获取每日利率
                WalletRule rule = walletRuleService.getRechargeRule();
                BigDecimal dailyInterestRate = rule.getDailyInterestRate();
                if (dailyInterestRate == null) {
                    dailyInterestRate = BigDecimal.valueOf(0.001); // 默认0.1%
                }
                cur = cur.add(cur.multiply(dailyInterestRate));
                wallet.setCurrentOverdraftAmount(cur);
                walletMapper.updateById(wallet);
                log.info(String.valueOf(wallet.getCurrentOverdraftAmount()));
            }
        }
    }

}
